﻿using System;
using System.Diagnostics;
using System.IO;
using MkLink;
using SymbolicLinkManageCore.Exceptions;

namespace SymbolicLinkManageCore.Library.UsersAndPermissions
{
    public class ShellExecuteTools
    {
        public static void SystemMklink(LinkType linkType, PathType pathType, string LinkPointPath, string LinkTargetPath)
        {
            string? lppRoot = Path.GetPathRoot(LinkPointPath);
            string? ltpRoot = Path.GetPathRoot(LinkTargetPath);
            if (string.IsNullOrWhiteSpace(lppRoot) || string.IsNullOrWhiteSpace(ltpRoot))
                throw new ArgumentNullException($"目录必须都是绝对路径 [{nameof(LinkPointPath)}:{LinkPointPath}] [{nameof(LinkTargetPath)}:{LinkTargetPath}]");
            string lt = string.Empty;
            if (linkType == LinkType.SYMLINK)
            {
                if (pathType == PathType.FileType)
                    lt = string.Empty;
                else throw new ArgumentException($"参数{nameof(linkType)}:[{linkType}] 与 {nameof(pathType)}:[{pathType}],之间不匹配，文件型符号连接仅支持文件类型的操作！");
            }
            else if(linkType == LinkType.SYMLINKD)
            {
                if(pathType == PathType.DirectoryType)
                    lt = @"/D";
                else throw new ArgumentException($"参数{nameof(linkType)}:[{linkType}] 与 {nameof(pathType)}:[{pathType}],之间不匹配，目录型符号连接仅支持目录类型的操作！");
            }
            else if (linkType == LinkType.JUNCTION)
            {
                if (pathType == PathType.DirectoryType)
                    lt = @"/J";
                else throw new ArgumentException($"参数{nameof(linkType)}:[{linkType}] 与 {nameof(pathType)}:[{pathType}],之间不匹配，目录联接不支持文件类型的操作");
            }
            else if (linkType == LinkType.HardLink)
            {
                if (pathType == PathType.FileType && lppRoot.Equals(ltpRoot, StringComparison.OrdinalIgnoreCase))
                    lt = @"/H";
                else throw new ArgumentException($"参数{nameof(linkType)}:[{linkType}] 与 {nameof(pathType)}:[{pathType}],之间不匹配，[{nameof(LinkPointPath)}根目录:{lppRoot} {nameof(LinkTargetPath)}:{ltpRoot}],硬链接只支持文件类型且必须在同一个根目录中");
            }
            else
                throw new ArgumentException($"参数[{nameof(linkType)}:[{linkType}]  {nameof(pathType)}:[{pathType}]], [[{nameof(LinkPointPath)}:{LinkPointPath}] [{nameof(LinkTargetPath)}:{LinkTargetPath}]],未知错误");
            string err;
            using (Process  process = new Process()) 
            {
                process.StartInfo.FileName = "cmd";
                process.StartInfo.Arguments = $"/C \"{$"mklink {lt} \"{LinkPointPath}\" \"{LinkTargetPath}\""}\"";
                process.StartInfo.Verb = "runas";
                process.StartInfo.CreateNoWindow = true;
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardError = true;
                //process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                process.Start();
                err = process.StandardError.ReadToEnd();
            }
            if (!string.IsNullOrWhiteSpace(err))
                throw new MklinkException($"执行错误:{err}");
        }

        public static void SystemMklink(LinkType linkType, string LinkPointPath, string LinkTargetPath)
        {
            int err;
            using (Process process = new Process())
            {
                process.StartInfo.FileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Tools", "MklinkRunas.exe");
                process.StartInfo.Arguments = $"{LinkPointPath} {LinkTargetPath} {linkType}";
                process.StartInfo.Verb = "runas";
                process.StartInfo.UseShellExecute = true;
                process.Start();
                process.WaitForExit();
                err = process.ExitCode;
            }
            if (err < 0)
            {
                _ = err switch
                {
                    -1 => throw new MklinkException($"执行错误:{err} 缺少参数"),
                    -2 => throw new MklinkException($"执行错误:{err} LinkPointPath:[{LinkPointPath}] 路径错误"),
                    -3 => throw new MklinkException($"执行错误:{err} LinkTargetPath:[{LinkTargetPath}] 路径错误"),
                    -4 => throw new MklinkException($"执行错误:{err} LinkType:[{linkType}] 连接类型参数错误"),
                    -5 => throw new MklinkException($"执行错误:{err} 创建连接错误"),
                    0 => 0,
                    _ => throw new NotImplementedException()
                };
            }
        }

        public static void AddregInfo(string ExePate)
        {
            int err;
            using (Process process = new Process())
            {
                process.StartInfo.FileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Tools", "MklinkRunas.exe");
                process.StartInfo.Arguments = $"AddregInfo \"{ExePate}\"";
                process.StartInfo.Verb = "runas";
                process.StartInfo.UseShellExecute = true;
                process.Start();
                process.WaitForExit();
                err = process.ExitCode;
            }
            if (err == -5)
                throw new AddRegException("注册系统右键菜单,注册失败~!");
        }
    }
}
